using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Sunny.UI;

public static class Mapper
{
	private static void Execute<T1, T2>(T1 source, T2 dest) where T1 : class, new() where T2 : class, new()
	{
		if (source == null || dest == null)
		{
			return;
		}
		Dictionary<string, PropertyInfo> dictionary = source.GetType().GetNeedProperties().ToDictionary((PropertyInfo prop) => prop.Name);
		foreach (KeyValuePair<string, PropertyInfo> item in dest.GetType().GetNeedProperties().ToDictionary((PropertyInfo prop) => prop.Name))
		{
			if (dictionary.NotContainsKey(item.Key))
			{
				continue;
			}
			PropertyInfo propertyInfo = dictionary[item.Key];
			Type propertyType = propertyInfo.PropertyType;
			object value = propertyInfo.GetValue(source, null);
			PropertyInfo value2 = item.Value;
			Type propertyType2 = item.Value.PropertyType;
			if (!propertyType.Equals(propertyType2))
			{
				continue;
			}
			if (propertyType.IsValueType)
			{
				value2.SetValue(dest, value, null);
			}
			else if (propertyType == typeof(string))
			{
				value2.SetValue(dest, value, null);
			}
			else if (propertyType.IsList())
			{
				Type[] genericArguments = propertyType.GetGenericArguments();
				Type[] genericArguments2 = propertyType2.GetGenericArguments();
				if (genericArguments.Length != 1 || genericArguments2.Length != 1 || !genericArguments[0].Equals(genericArguments2[0]))
				{
					continue;
				}
				if (value == null)
				{
					value2.SetValue(dest, null, null);
					continue;
				}
				Type type = typeof(List<>).MakeGenericType(genericArguments2[0]);
				MethodInfo method = type.GetMethod("Add", BindingFlags.Instance | BindingFlags.Public);
				if (method == null || (!genericArguments[0].IsValueType && !(genericArguments[0] == typeof(string))))
				{
					continue;
				}
				object obj = type.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, new object[0]);
				foreach (object item2 in value as IEnumerable)
				{
					method.Invoke(obj, new object[1] { item2 });
				}
				value2.SetValue(dest, obj, null);
			}
			else if (propertyType.IsArray)
			{
				if (value == null)
				{
					value2.SetValue(dest, null, null);
					continue;
				}
				ICollection collection = value as ICollection;
				Array array = Array.CreateInstance(propertyType.GetElementType(), collection.Count);
				int num = 0;
				foreach (object item3 in collection)
				{
					array.SetValue(item3, num++);
				}
				value2.SetValue(dest, array, null);
			}
			else
			{
				propertyType.IsDictionary();
			}
		}
	}

	public static void MapperTo<T1, T2>(this T1 source, T2 dest) where T1 : class, new() where T2 : class, new()
	{
		Execute(source, dest);
	}

	public static void MapperFrom<T1, T2>(this T1 dest, T2 source) where T1 : class, new() where T2 : class, new()
	{
		Execute(source, dest);
	}

	public static Type GetArrayElementType(this Type t)
	{
		if (!t.IsArray)
		{
			return null;
		}
		string name = t.FullName.Replace("[]", string.Empty);
		return t.Assembly.GetType(name);
	}
}
